package com.skydonkey.controller;


import com.alibaba.druid.util.StringUtils;
import com.github.pagehelper.Page;
import com.skydonkey.config.RedisConfig;
import com.skydonkey.pojo.po.Category;
import com.skydonkey.pojo.po.VideoInfo;
import com.skydonkey.pojo.vo.*;
import com.skydonkey.service.VideoService;
import com.skydonkey.utils.*;
import com.skydonkey.validator.AccountValidator;
import com.skydonkey.validator.CommonValidator;
import com.skydonkey.verify.PassToken;
import com.skydonkey.verify.VerifyToken;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;

@RestController
@RequestMapping(path = "/video")
public class VideoController {

    private static final Logger log = LoggerFactory.getLogger(VideoController.class);

    private static final String KEY_TEMP_UPLOAD_VIDEO_KEY = "skydonkey:video:upload:video" + RedisConfig.DECOLLATOR ;   //暂存视频
    private static final String KEY_TEMP_UPLOAD_VIDEO_COVER_KEY = "skydonkey:video:upload:cover" + RedisConfig.DECOLLATOR ;   //暂存视频封面

    @Autowired
    RedisUtils redisUtils;

    @Autowired
    QiniuUtils qiniuUtils;

    @Autowired
    VideoService videoService;

    @RequestMapping(path = "/upload", method = RequestMethod.GET)
    public Result UploadVideo() {
        String filename = "R]DQ`L162BG{S$T}8LM72}2.png";
        String filePath = "J:\\WORK\\MC\\WaitWhat\\第八期\\" + filename;
        byte[] data = FileUtils.readToByteArray(filePath);
        String downloadUrl = qiniuUtils.uploadFile(filename, data);
        Result result = new Result(ResultEnum.SUCCESS, downloadUrl);
        return result;
    }

    @VerifyToken
    @RequestMapping(path = "/upload/cover", method = RequestMethod.POST)
    public Result<UploadFileResp> uploadVideoCover(
        @RequestParam("file") MultipartFile file,
        @RequestParam("originName") String originName,
        @RequestParam("uid") Long uid) throws IOException {
        String[] split = originName.split("\\.");
        String suffix = split[split.length - 1];
        String key = UUID.randomUUID() + "." + suffix;
        String downloadUrl = qiniuUtils.uploadFile(key, file.getBytes());
        UploadFileResp uploadVideoResp = new UploadFileResp()
                .setKey(key)
                .setUrl(downloadUrl);
        // 1.记录u    rl,key和id到redis
        redisUtils.sSet(KEY_TEMP_UPLOAD_VIDEO_COVER_KEY + uid.toString(),
                ObjectMapperUtil.toJSON(uploadVideoResp));
        //TODO 2.发送日志到mq, 记录日志
        return new Result<UploadFileResp>(ResultEnum.SUCCESS, uploadVideoResp);
    }

    //上传视频,但仅上传视频和用户id, 返回文件key和url
    @VerifyToken
    @RequestMapping(path = "/upload", method = RequestMethod.POST)
    public Result<UploadFileResp> uploadVideo(
            HttpServletRequest request,
            @RequestParam("file") MultipartFile file,
            @RequestParam("originName") String originName,
            @RequestParam("uid") Long uid) throws IOException {
        if(!AccountValidator.isValid(request, uid)){
            return Result.failed(null);
        }

        // 获取视频时长
        Long videoDuration = null;
        try {
            log.info(file.getOriginalFilename());
            videoDuration = SkydonkeyUtils.getVideoDuration(file);
            if(videoDuration == -1){
                return Result.failed(null);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Result.failed(null);
        }

        log.info("filename: " + file.getName());
        log.info("file size: " + file.getBytes().length);
        log.info("uid: " + uid);
        // 重新生成一个新的文件名, 用uuid
        String[] split = originName.split("\\.");
        String suffix = split[split.length - 1];
        String key = UUID.randomUUID() + "." + suffix;
        String downloadUrl = qiniuUtils.uploadFile(key, file.getBytes());
        UploadFileResp uploadVideoResp = new UploadFileResp()
                .setKey(key)
                .setUrl(downloadUrl);

        // 1.记录url,key和id到redis
        redisUtils.sSet(KEY_TEMP_UPLOAD_VIDEO_KEY + uid.toString(),
                ObjectMapperUtil.toJSON(uploadVideoResp));


        uploadVideoResp.setDuration(videoDuration);

        //TODO 2.发送日志到mq, 记录日志
        return new Result<>(ResultEnum.SUCCESS, uploadVideoResp);
    }

    @PassToken
    @RequestMapping(path = "/category/all", method = RequestMethod.GET)
    public Result<List<Category>> getAllVideoCategories() {
        List<Category> allCategories = videoService.getAllCategories();
        return new Result<>(ResultEnum.SUCCESS, allCategories);
    }

    // 发布视频
    @VerifyToken
    @RequestMapping(path = "/publish", method = RequestMethod.POST)
    public Result<VideoPublishResp> publishVideo(@RequestBody VideoPublishReq req) {
        log.info("publishVideo: " + req);
        try{
            return videoService.publishVideo(req);
        }catch (Exception e){
            e.printStackTrace();
            return Result.failed(null);
        }
    }

    // 获取我的发布的视频
    @VerifyToken
    @RequestMapping(path = "/published/self", method = RequestMethod.POST)
    public Result<QueryPublishedVideoResp> queryPublishedVideos(
            HttpServletRequest request,
            @RequestBody QueryPublishedVideoReq req
    ){

        if (CommonValidator.hasEmptyFields(req) ||
                !AccountValidator.isValid(request, req.getUid())){
            return Result.failed(null);
        }
        QueryPublishedVideoResp resp = videoService.getPublishedVideo(req);
        return Result.success(resp);
    }


    //按视频类型获取视频分页
    @PassToken
    @RequestMapping(path = "/get/{categoryId}/{pageNum}/{pageCount}", method = RequestMethod.GET)
    public Result<QueryCategoryVideoResp> queryVideoByCategory(
            @PathVariable("categoryId") Integer categoryId,
            @PathVariable("pageNum") Integer pageNum,
            @PathVariable("pageCount") Integer pageCount
    ){
        Page<VideoInfo> videoInfos = null;
        // 判断是否请求的热门视频
        if(categoryId == -1){
            videoInfos = videoService.getMostLikedVideoInfo(pageNum, pageCount);
        }else{
            videoInfos = videoService.findVideoInfoByCategoryId(categoryId, pageNum, pageCount);
            if(videoInfos.getResult().size() == 0){
                videoInfos = videoService.findAll(pageNum, pageCount);
            }
        }
        QueryCategoryVideoResp resp = new QueryCategoryVideoResp().setVideoInfos(videoInfos);
        return Result.success(resp);
    }

    @PassToken
    @RequestMapping(path = "/get/{videoId}", method = RequestMethod.GET)
    public Result<GetVideoInfoResp> queryVideoByCategory(
            @PathVariable("videoId") Long videoId
    ){
        VideoInfo videoInfo = videoService.getVideoInfoByVid(videoId);
        GetVideoInfoResp resp = new GetVideoInfoResp();
        resp.setVideoInfo(videoInfo);
        return Result.success(resp);
    }


    /**
     * 视频-添加我喜欢
     */
    @VerifyToken
    @RequestMapping(path = "/like/add", method = RequestMethod.POST)
    public Result<AddVideoMyLikedResp> addVideoMyLiked(
            HttpServletRequest request,
            @RequestBody AddVideoMyLikedReq req) {
        if (CommonValidator.hasEmptyFields(req) ||
            !AccountValidator.isValid(request, req.getUid())){
            return Result.failed(null);
        }

        int re = videoService.addVideoMyLiked(req);
        if(re == 0){
            return Result.failed(null);
        }
        return Result.success(null);
    }


    /**
     * 视频-删除我喜欢
     */
    @VerifyToken
    @RequestMapping(path = "/like/del", method = RequestMethod.POST)
    public Result<DeleteVideoMyLikedResp> delVideoMyLiked(
            HttpServletRequest request,
            @RequestBody DeleteVideoMyLikedReq req) {
        if (CommonValidator.hasEmptyFields(req) ||
                !AccountValidator.isValid(request, req.getUid())){
            return Result.failed(null);
        }

        int re = videoService.deleteVideoMyLiked(req);
        if(re == 0){
            return Result.failed(null);
        }
        return Result.success(null);
    }


    @VerifyToken
    @RequestMapping(path = "/like/list", method = RequestMethod.POST)
    public Result<GetVideoMyLikedDetailsResp> getVideoMyLikedDetails(
            HttpServletRequest request,
            @RequestBody GetVideoMyLikedDetailsReq req) {
        if(CommonValidator.hasEmptyFields(req)){
            return Result.failed(null);
        }
        if(!AccountValidator.isValid(request, req.getUid())){
            return Result.failed(null);
        }
        return Result.success(videoService.getVideoMyLikedDetails(req));
    }

    /**
     * 视频-添加我的收藏
     */
    @VerifyToken
    @RequestMapping(path = "/fav/add", method = RequestMethod.POST)
    public Result<AddVideoMyFavResp> addVideoFav(
            HttpServletRequest request,
            @RequestBody AddVideoMyFavReq req) {
        if (CommonValidator.hasEmptyFields(req) ||
                !AccountValidator.isValid(request, req.getUid())){
            return Result.failed(null);
        }
        int re = videoService.addVideoMyFavoriteVideo(req);
        if(re == 0){
            return Result.failed(null);
        }
        return Result.success(null);
    }

    /**
     * 视频-删除我的收藏
     */
    @VerifyToken
    @RequestMapping(path = "/fav/del", method = RequestMethod.POST)
    public Result<DeleteVideoMyFavResp> delVideoFav(
            HttpServletRequest request,
            @RequestBody DeleteVideoMyFavReq req) {
        if (CommonValidator.hasEmptyFields(req) ||
                !AccountValidator.isValid(request, req.getUid())){
            return Result.failed(null);
        }
        int re = videoService.deleteVideoMyFavorite(req);
        if(re == 0){
            return Result.failed(null);
        }
        return Result.success(null);
    }


    //获取我的收藏
    @VerifyToken
    @RequestMapping(value = "/fav/list", method = RequestMethod.POST)
    public Result<GetVideoMyFavResp> getVideoMyFav(HttpServletRequest request,
                                                   @RequestBody GetVideoMyFavReq req) {
        if(CommonValidator.hasEmptyFields(req)){
            return Result.failed(null);
        }
        if(!AccountValidator.isValid(request, req.getUid())){
            return Result.failed(null);
        }
        return Result.success(videoService.getFavoriteVideos(req));
    }

    /**
     * 视频-添加观看历史记录
     */
    @PassToken
    @RequestMapping(path = "/history/add", method = RequestMethod.POST)
    public Result<AddVideoWatchHistoryResp> addVideoWatchHistory(
            HttpServletRequest request,
            @RequestBody AddVideoWatchHistoryReq req){

        // 未登录用户
        if(req.getUid() == null){
            if(req.getVideoId() == null){
                return Result.failed(null);
            }
            //添加播放次数
            videoService.addVideoWatchTimes(req.getVideoId());
            return Result.success(null);
        }
        // 登录用户
        if (CommonValidator.hasEmptyFields(req) ||
                !AccountValidator.isValid(request, req.getUid())){
            return Result.failed(null);
        }
        int re = videoService.addVideoWatchHistory(req);
        videoService.addVideoWatchTimes(req.getVideoId());
        return re == 0 ? Result.failed(null) : Result.success(null);
    }



    /**
     * 视频-删除观看历史记录
     */
    @VerifyToken
    @RequestMapping(path = "/history/del", method = RequestMethod.POST)
    public Result<DeleteVideoWatchHistoryResp> delVideoWatchHistory(
            HttpServletRequest request,
            @RequestBody DeleteVideoWatchHistoryReq req){
        if (CommonValidator.hasEmptyFields(req) ||
                !AccountValidator.isValid(request, req.getUid())){
            return Result.failed(null);
        }
        int re = videoService.deleteVideoWatchHistory(req);
        if(re == 0){
            return Result.failed(null);
        }
        return Result.success(null);
    }


    @VerifyToken
    @RequestMapping(value = "/history/get", method = RequestMethod.POST)
    public Result<GetVideoHistoryListResp> getVideoHistoryList(
            HttpServletRequest request,
            @RequestBody GetVideoHistoryListReq req
    ) {
        if(CommonValidator.hasEmptyFields(req) || !AccountValidator.isValid(request, req.getUid())){
            return Result.failed(null);
        }
        GetVideoHistoryListResp resp = videoService.getVideoWatchHistory(req);
        return Result.success(resp);
    }


    // 获取一个视频的历史观看次数
    @PassToken
    @RequestMapping(path = "/wt/get/{videoId}", method = RequestMethod.GET)
    public Result<Long> getVideoWatchTimes(@PathVariable("videoId") Long videoId){
        return Result.success(videoService.getVideoWatchTimes(videoId).getWatchTimes());
    }

    // 添加一个视频的历史观看次数
    @PassToken
    @RequestMapping(path = "/wt/add/{videoId}", method = RequestMethod.GET)
    public Result<Long> addVideoWatchTimes(@PathVariable("videoId") Long videoId) {
        return Result.success(videoService.addVideoWatchTimes(videoId));
    }


    // 获取一个视频的相关详细信息， 包括点赞数，收藏数， 观看次数， 评论数，url， 发布者等
    @PassToken
    @RequestMapping(path = "/info/detail", method = RequestMethod.POST)
    public Result<VideoDetailsResp> getVideoDetails(
            HttpServletRequest request,
            @RequestBody VideoDetailsReq req){
        if (req == null) {
            return Result.failed(null);
        }
        VideoDetailsResp videoDetail = null;
        if(req.getUid() != null && req.getUid() != 0L){
            if(!AccountValidator.isValid(request, req.getUid())){
                return Result.failed(null);
            }
            videoDetail = videoService.getVideoDetailWithUserLikedFav(req.getUid(), req.getVideoId());
        }else{
            videoDetail = videoService.getVideoDetail(req.getVideoId());
        }
        if (videoDetail == null) {
            return Result.failed(null);
        }
        return Result.success(videoDetail);
    }


    // 获取推荐视频
    @PassToken
    @RequestMapping(path = "/rec/{pageNum}/{pageCount}", method = RequestMethod.GET)
    public Result<GetRecommendVideoDetailsResp> getRecommendVideoDetails(
            @PathVariable("pageNum") Integer pageNum,
            @PathVariable("pageCount") Integer pageCount
    ){
        long start = System.currentTimeMillis();
        GetRecommendVideoDetailsResp resp = videoService.getRecommendVideoDetail(pageNum, pageCount);
        long end = System.currentTimeMillis();
        log.info("执行耗时: " + (end - start) + "ms");
        return Result.success(resp);
    }


    @VerifyToken
    @RequestMapping(path = "/permission/update", method = RequestMethod.POST)
    public Result<UpdatePermissionResp> updatePermission(
            HttpServletRequest request,
            @RequestBody UpdatePermissionReq req){
        if(CommonValidator.hasEmptyFields(req) || !AccountValidator.isValid(request, req.getUid())){
            return Result.failed(null);
        }
        UpdatePermissionResp result = videoService.updateVideoPermission(req);
        return result == null ? Result.failed(null) : Result.success(result);
    }

    @VerifyToken
    @RequestMapping(path = "/delete", method = RequestMethod.POST)
    public Result<DeleteVideoPublishedResp> deletePublishedVideo(
            HttpServletRequest request,
            @RequestBody DeleteVideoPublishedReq req){
        if(CommonValidator.hasEmptyFields(req) || !AccountValidator.isValid(request, req.getUid())){
            return Result.failed(null);
        }
        DeleteVideoPublishedResp result = videoService.deletePublishedVideo(req);
        return result == null ? Result.failed(null) : Result.success(result);
    }

    @PassToken
    @RequestMapping(path = "/sample", method = RequestMethod.POST)
    public Result<GetVideoSamplesResp> getSamples(@RequestBody GetVideoSamplesReq req){
        if(CommonValidator.hasEmptyFields(req)){
            return Result.failed(null);
        }
        GetVideoSamplesResp samples = videoService.getVideoSamples(req);
        return Result.success(samples);
    }


    @VerifyToken
    @RequestMapping(path="/comment/add", method = RequestMethod.POST)
    public Result<CreateVideoCommentResp> createComment(
            HttpServletRequest request,
            @RequestBody CreateVideoCommentReq req){
        if(CommonValidator.hasEmptyFields(req) || !AccountValidator.isValid(request, req.getUid())){
            return Result.failed(null);
        }
        CreateVideoCommentResp comment = videoService.createComment(req);
        return Result.success(comment);
    }


    @PassToken
    @RequestMapping(path="/comment/get", method = RequestMethod.POST)
    public Result<GetVideoCommentResp> getComment(
            @RequestBody GetVideoCommentReq req
    ){
        GetVideoCommentResp comment = videoService.getComment(req);
        return Result.success(comment);
    }

    @PassToken
    @RequestMapping(path = "/search", method = RequestMethod.POST)
    public Result<SearchVideoResp> getSearch(@RequestBody SearchVideoReq req){
        SearchVideoResp resp = videoService.searchVideoIdByTitle(req);
        return Result.success(resp);
    }


}
